package com.xuzz.study.transaction;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.lang.reflect.Method;

/**
 * @author xuzz
 * @description
 * @date 2019-12-04 10:50
 */
@Component
@Aspect
public class XuzzAopTransaction {
    @Autowired
    TransactionUtils transactionUtils;

    @Before("execution(* com.xuzz.*.*.*(..))")
    public void before()
    {
        System.out.println("beform");
    }

    @Around("execution(* com.xuzz.*.*.*(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        XuzzTransaction xuzzTransaction = getXuzzTransactionAn(proceedingJoinPoint);
        TransactionStatus transactionStatus=null;
        if(null!=xuzzTransaction)
        {
            transactionStatus = transactionUtils.begin();
        }
        proceedingJoinPoint.proceed();
        if(null!=transactionStatus) {
            transactionUtils.commit(transactionStatus);
        }
    }

    @AfterThrowing("execution(* com.xuzz.*.*.*(..))")
    public void throwing(){
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }

    private XuzzTransaction getXuzzTransactionAn(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        String methodName = proceedingJoinPoint.getSignature().getName();
        Class<?> clazz= proceedingJoinPoint.getTarget().getClass();
        Class<?>[] params =((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes();
        Method method = clazz.getMethod(methodName,params);

        XuzzTransaction xuzzTransaction = method.getDeclaredAnnotation(XuzzTransaction.class);
        return xuzzTransaction;
    }
}
